package com.gvsoft;

import com.gvsoft.analyse.AnalyseTools;
import com.gvsoft.conns.GVConnection;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.channels.SocketChannel;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;


/**
 * Created with IntelliJ IDEA.
 * ProjectName:gvMsgRouting
 * Author: zhaoqiubo
 * Date: 15/8/5
 * Time: 上午8:34
 * Desc: 配置中心，初始化所有配置，保存系统常量及缓冲池
 *
 * 【一些约定】：
 * |-------------------------------------------
 * | 1、所有接收到的消息，称之为报文（Packet）
 * | 2、所有发出去的消息，称之为指令（Order）
 * |-------------------------------------------
 *
 */
public class Config {

    //服务绑定的端口
    private int port;
    //服务器IP地址
    private String ip;
    /**
     * 报文区间分隔符，报文分为三个区间，HEADER区间、RID区间、BODY区间；
     * HEADER标记报文分类，RID为报文对象id，在一定周期内唯一；BODY为报文的内容区域。
     */
    public static String HBREGEX = "|";
    /**
     * 存储所有报文处理类的实例，一次性初始化进入Map（为连接通道（GVServer中使用）准备的单例类Map）
     */
    private static Map<String, Object> SINGLE_INSTANCE_PACKET_CLASS_MAP = new ConcurrentHashMap();
    /**
     * 存储所有报文处理类的实例，一次性初始化进入Map（为消息处理线程（CommunicateQueueConsumer中使用）准备的单例消息处理类Map）
     */
    private static Map<String, Object> SINGLE_INSTANCE_ORDER_CLASS_MAP = new ConcurrentHashMap();
    /**
     * 配置报文处理类分类的外部分隔符，分隔符两边代表某一类报文处理类的属性描述。
     * 例如：R:com.gvsoft.analyse.RegisterHandleModel|E:com.gvsoft.analyse.ErrorHandleModel
     */
    private final String SeparatorOuter = "|";
    /**
     * 配置报文处理类分类的内部部分隔符,分割某一类报文处理类的header和body。
     * 例如：R:com.gvsoft.analyse.RegisterHandleModel
     */
    private final String SeparatorInner = ":";
    /**
     * 存储所有活跃连接，key值存储token
     */
//    public static Map<String,GVConnection> ACTIVED_CHANNELS_BY_TOKEN = new ConcurrentHashMap<String,GVConnection>();
    /**
     * 存储所有活跃连接，key值存储SocketChannel，要求与ACTIVED_CHANNELS_BY_CLIENT同步
     */
    /*暂时先不采用双Map机制控制连接Map维护，zhaoqb，20150806
    public static Map<SocketChannel,GVConnection> ACTIVED_CHANNELS_BY_CHANNELS = new ConcurrentHashMap<SocketChannel,GVConnection>();
    */
    /*
    连接的超时时间
     */
    public int cleanThreadOutTime;
    /**
     * 连接清理线程的执行周期
     */
    public int cleanThreadCycle;
    /*
    通讯队列消费者，队列中没有对象时的等待时间
     */
    public int waitTime;

    /**
     * 网络报文读取缓冲区大小
     */
    private static int readBlock=4096;
    /**
     * 指令写入缓冲区大小
     */
    private static int writeBlock=1024;

    private static Logger logger = LogManager.getLogger(Config.class.getName());

    public Config(String config) {
        initConfig(config);
        //Config.SINGLE_INSTANCE_CLASS_MAP.put("config",this);
    }

    /**
     * 初始化所有配置，包括ip、port、连接超时时间、清理连接周期，初始化单例处理类的两个缓冲池
     * @param config
     */
    private void initConfig(String config) {
        //YMP.initialize();
        Properties p = new Properties();
        try {
            InputStreamReader reader = new InputStreamReader(new FileInputStream
                    (config), "utf-8");
            p.load(reader);
            this.ip = p.getProperty("server_ip");
            this.port = Integer.parseInt(p.getProperty("server_port").trim());
            this.cleanThreadOutTime = Integer.parseInt(p.getProperty("timeout_seconds").trim());
            this.cleanThreadCycle = Integer.parseInt(p.getProperty("clean_thread_cycle").trim());
            this.waitTime = Integer.parseInt(p.getProperty("wait_time").trim());
            this.readBlock = Integer.parseInt(p.getProperty("read_block").trim());
            this.writeBlock = Integer.parseInt(p.getProperty("write_block").trim());

            initPacketMap(p.getProperty("packet_class"));
            initOrderMap(p.getProperty("order_class"));

            logger.info("GVServer消息路由服务配置初始化完成！");
            logger.info("—————————————————————————————————————————————————————————————————");
            logger.info("|【特别鸣谢】：有理想的鱼、旅客列车、任我飞、宋阳、砒霜大力丸、凌云、小胖！|");
            logger.info("—————————————————————————————————————————————————————————————————");


        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 初始化报文实例池
     * @param handleCfgStr
     */
    private void initPacketMap(String handleCfgStr) {
        String[] handleOuterArray = AnalyseTools.str2ArrayByChar(handleCfgStr, SeparatorOuter);
        try {
            for (int i = 0; i < handleOuterArray.length; i++) {
                String[] handleInnerArray = AnalyseTools.str2ArrayByChar(handleOuterArray[i], SeparatorInner);
                Class c = Class.forName(handleInnerArray[1]);
                Object handleClass = c.newInstance();
                Config.SINGLE_INSTANCE_PACKET_CLASS_MAP.put(handleInnerArray[0], handleClass);
            }
            logger.info("报文实例池单例类加载完毕…………");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化指令实例池
     * @param handleCfgStr
     */
    private void initOrderMap(String handleCfgStr) {
        String[] handleOuterArray = AnalyseTools.str2ArrayByChar(handleCfgStr, SeparatorOuter);
        try {
            for (int i = 0; i < handleOuterArray.length; i++) {
                String[] handleInnerArray = AnalyseTools.str2ArrayByChar(handleOuterArray[i], SeparatorInner);
                Class c = Class.forName(handleInnerArray[1]);
                Object handleClass = c.newInstance();
                Config.SINGLE_INSTANCE_ORDER_CLASS_MAP.put(handleInnerArray[0], handleClass);
            }
            logger.info("指令实例池单例类加载完毕…………");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 从报文实例池中取出操作实例
     * @param classKey
     * @return
     */
    public static Object getPacketInstance(String classKey) {
        return Config.SINGLE_INSTANCE_PACKET_CLASS_MAP.get(classKey);
    }

    /**
     * 从指令实例池中取出操作实例
     * @param classKey
     * @return
     */
    public static Object getOrderInstance(String classKey) {
        return Config.SINGLE_INSTANCE_ORDER_CLASS_MAP.get(classKey);
    }

    /**
     * 根据token从通道缓冲池中取出通道
     * @param token
     * @return
     */
/*    public static SocketChannel getChannelByToken(String token){
        if (Config.ACTIVED_CHANNELS_BY_TOKEN.get(token)==null){
            return null;
        }else{
            return (SocketChannel)Config.ACTIVED_CHANNELS_BY_TOKEN.get(token).getChannel();
        }
    }*/

    /**
     * 根据token从通道缓冲池中取出GVConnection
     * @param token
     * @return
     */
/*    public static GVConnection getGVConnectionByToken(String token){
        return Config.ACTIVED_CHANNELS_BY_TOKEN.get(token);
    }*/
    /**
     * 保存通道信息到通道缓冲池
     * @param
     */
/*    public static void addChannel(GVConnection gvConn){
        Config.ACTIVED_CHANNELS_BY_TOKEN.put(gvConn.getToken(), gvConn);
    }*/

    public int getPort() {
        return port;
    }

    public String getIp() {
        return ip;
    }

    public int getCleanThreadOutTime() {
        return cleanThreadOutTime;
    }

    public int getCleanThreadCycle() {
        return cleanThreadCycle;
    }

    public int getWaitTime() {
        return waitTime;
    }

    public static int getReadBlock() {
        return readBlock;
    }

    public static int getWriteBlock() {
        return writeBlock;
    }

}
